"""
@author: xxw
@file: 2023-6-6-迭代器与生成器.py
@time: 2023/6/6 14:33
"""

# 推导式
# 列表推导式
# 字典推导式
# 集合推导式

# 1、列表推导式
# str1 = "abcdefg"
# list1 = [x.upper() for x in str1]
# print(list1)
# list1 = [x.upper() for x in str1 if ord(x) > 100]
# print(list1)
#
# #打印50以内能被3整除的数的平方
# list2 = [ x ** 2 for x in range(1, 50) if x % 3 == 0 ]
# print(list2)
#
# names = [["sc", "chenli", "tangyuzhi"],
#          ["chenyingting", "yinjiaxing"]]
# result = [name for list in names for name in list if "g" in name]
#
# lst = [2.34354, 4.768245]
#
# # 集合推导式 -- 跟列表推导式类似 -- 使用{}
# # 自带去重
# lst = [-1, 1, 2, -2, 4, 5]
# s1 = { abs(x) for x in lst}
# print(s1)

# 字典推导式
# d1 = {"a":1, "b":2}
# d2 = {v: k for k, v in d1.items()}
# print(d2)

# d3 = {k.upper(): v for k, v in d1.items()}
# print(d3)

# q1 = ['a','ab','abc','abcd','abcde']
# q2 = [ i.upper() for i in q1 if len(i) >= 3]
# print(q2)
#
# t1 = [(x, y) for x in range(0, 6) for y in range(0, 6) if x % 2 == 0 and y % 2 == 1]
# print(t1)
#
# q4 = {'B':3,'a':1,'b':6,'c':3,'A':4}
# q5 = { k.lower(): q4.get(k.lower(),0) + q4.get(k.upper(),0) for k in q4  }
# print(q5)

###############
# 可迭代对象、迭代器、生成器
# 可迭代对象：
# 实现了__iter__方法，并且该方法返回一个迭代器对象
# str1 = "abc"
# print(dir(str1))
# iterator_str1 = str1.__iter__()
# print(dir(iterator_str1))
# print(iterator_str1.__next__())
# print(iterator_str1.__next__())
# print(iterator_str1.__next__())


# 迭代器
# 实现了__iter__和__next__的方法，这样子的对象叫做迭代器对象
# __iter__方法返回自身
# __next__方法返回下一个值

# for 语法糖
# for 先调用可迭代对象的__iter__方法，该方法返回一个迭代器
#   再对迭代对象调用__next__方法，不断获取下一个值，直到获取完成 抛出stopiterration异常 退出

# 迭代器 -- 懒加载，惰性求值， 需要的时候生成  节省空间
# lst = [1, 2, 3, 4, 5]
# print([x*x for x in lst])
# res = map(lambda x: x*x, lst)
# print(dir(res))
# print(res.__next__())

# 实现一个迭代器
class MyIter():
    def __init__(self, num=1, count=1):
        self.num = num
        self.count = count
        self.ticks = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.ticks > self.count:
            raise StopIteration
        self.num = self.ticks * self.num
        self.ticks += 1
        return self.num


n = MyIter(count=5)
for i in n:
    print(i)

# class sequence():
#     def __init__(self, a=0, b=1, max=1):
#         self.a = a
#         self.b = b
#         self.max = max
#
#     def __iter__(self):
#         return self
#
#     def __next__(self):
#         if self.b > self.max:
#             raise StopIteration
#         self.a, self.b = self.b, self.a + self.b
#         return self.b
# s = sequence(max=100)
# for i in s:
#     print(i)

# 生成器 一种特殊的迭代器
# 是迭代器更优雅的写法，不需要自己手动实现__iter__和__next__方法
# 生成器只有两个写法  一种叫做生成器表达式，一种叫做生成器函数

# 生成器表达式 -- 惰性求值
# 类似于列表推导式

# result = (x**2 for x in range(1, 21) if x % 3 == 0)
# for i in result:
#     print(i)

# 生成器函数
# 包含了yield关键字的函数就叫做生成器函数
# yield关键字：返回yield关键字后的表达式内容，保留中间算法，下次继续执行
# def fib(max):
#     prev, curr = 0, 1
#     while curr < max:
#         yield curr
#         prev, curr = curr, prev+curr
# f = fib(100)
# for i in f:
#     print(i)

# 生成器：可以用更少的代码来实现迭代器的效果
# 相比于容器类型更加节省空间

# 大文件处理
# fp = open("a.txt")
# for line in fp:
#     print(line)

# 使用生成器最好的场景：当你需要以迭代的方式去处理一个巨大的数据集合
# def read_file(fpth):
#     BLOCK_SIZE = 1024
#     with open(fpth, 'rb') as f:
#         while True:
#             block = f.read(BLOCK_SIZE)
#             if block:
#                 yield block
#             else:
#                 return

# send向生成器发送值
# def send_val():
#     count = 0
#     while 1:
#         val = yield count
#         if val is not None:
#             print(f"val is {val}")
#             count += 10
#         else:
#             count += 1
# s1 = send_val()
# print(next(s1))
# print(next(s1))
# print(s1.send(100))
# print(next(s1))

# yield 与 yield from 的区别

# def g1():
#     yield  range(10)
# def g2():
#     yield from range(10)
#
# g11 = g1()
# g22 = g2()
#
# for i in g11:
#     print(i)
#
# for i in g22:
#     print(i)

# yield from 后面必须接可迭代对象

# with open('a.txt') as f:
#     print(f.read())